//unsigned char *videoram = (unsigned char *) 0xb8000;

/*
void kputc(const char c, const char color) {
	*(videoram++) = c;
	*(videoram++) = color;
}

void kputs(const char * c, const char color) {
	kputc(*c, color);
	while (*(++c) != '\0') {
		kputc(*c, color);
	}
}
*/

static __inline__ void outb(unsigned short port, unsigned char val)
{
   asm volatile("outb %0,%1"::"a"(val), "dN" (port));
}

static __inline__ unsigned char inb(unsigned short port)
{
   unsigned char ret;
   asm volatile ("inb %1,%0":"=a"(ret):"dN"(port));
   return ret;
}


void mode13h() {

	/*** CRT CONTROLLER REGISTERS ***/
	unsigned char  CRTCRegs[] = {
		0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0xBF, 0x1F,
		0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x9C, 0x0E, 0x8F, 0x28, 0x40, 0x96, 0xB9, 0xA3,
		0xFF
	};
	unsigned int CRTCRegsSize =  25;
	
	/*** ATTRIBUTE CONTROLLER REGISTERS ***/
	unsigned char ACRegs[] = {
		0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
		0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
		0x41, 0x00, 0x0F, 0x00, 0x00
	};
	unsigned int ACRegsSize = 21;
	
	/*** GRAPHICS CONTROLLER REGISTERS ***/
	unsigned char GCRegs[] = {
		0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
		0xFF
	};
	unsigned int GCRegsSize = 9;
	
	/*** SEQUENCER REGISTERS ***/
	unsigned char SEQRegs[] = {
		0x03, 0x01, 0x0F, 0x00, 0x0E
	};
	unsigned int SEQRegsSize = 5;
	
	/*** ******************* ***/
	/*** ******************* ***/
	
	unsigned int i, q;
	
	outb(0x3C2, 0x63);                  // Misc register
	
	for(i = 0; i < SEQRegsSize; i++) {
		outb(0x3C4, i);
		outb(0x3C5, SEQRegs[i]);
	}
	
	// Enable CRTC regs
	outb(0x3D4, 0x03);
	outb(0x3D5, inb(0x3D5) | 0x80);
	outb(0x3D4, 0x11);
	outb(0x3D5, inb(0x3D5) & ~0x80);

	// make sure they stay enabled
	CRTCRegs[0x03] |= 0x80;
	CRTCRegs[0x11] &= ~0x80;

	for(i = 0; i < CRTCRegsSize; i++) {
		outb(0x3D4, i);
		outb(0x3D5, CRTCRegs[i]);
	}
	for(i = 0; i < GCRegsSize; i++) {
		outb(0x3CE, i);
		outb(0x3CF, GCRegs[i]);
	}
	for(i = 0; i < ACRegsSize; i++) {
		q = inb(0x3DA); q = q;
		outb(0x3C0, i);
		outb(0x3C0, ACRegs[i]);
	}

	q = inb(0x3DA); q = q;
	outb(VGA_AC_INDEX, 0x20);

}


static inline void setp(int x, int y, unsigned char color) {
	static unsigned char * vga_mem = (unsigned char *) 0xA0000;
	if (x > 320 || x < 0 || y > 200 || y < 0) return;
	vga_mem[320 * y + x] = color;
}

static inline char getp(int x, int y) {
	static unsigned char * vga_mem = (unsigned char *) 0xA0000;
	//if (x < 0 || x > 320 || y < 0 || y > 200) return 0;
	return vga_mem[320 * y + x];
	
}



void vga_clear()
{
	int x;
	int y;
	for(y=0;y<200;y++) {
		for(x=0;x<320;x++) {
			setp(x, y, 0);
		}
	}
}

void set_color(unsigned char c, unsigned char r, unsigned char g, unsigned char b) {
	outb(0x3C8, c);
	outb(0x3C9, r);
	outb(0x3C9, g);
	outb(0x3C9, b);
}

void set_pallette() {
	int i;
	for (i = 0; i < 255; i++) {
		set_color(i, i * .1, i * .18, i * .25);
	}
}



extern "C" void _kmain();

void _kmain() {

	mode13h();
	
	vga_clear();
	
	set_pallette();
	
	int x = 0;
	int y = 0;
	//int colordir = 1;
	unsigned char color = 0;
	
	while (1) {
		color++;
		if (color > 254) color = 0;
		
		
		x += 1;
		y += 1;
		setp(x, y, color);
	}
	

}

















